﻿namespace IBTrader.Model
{
    using IBTrader.Frontend;
    using IBTrader.Modules.Market;
    using IBTrader.Modules.Tws;
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Xml.Serialization;

    public class Orders : ObservableCollection<Order> 
    {
        public Summary GetSummary() { return new Summary(this); }
        public class Summary
        {
            public IEnumerable<Order> Filled, Bought, Sold;
            public double Summ;
            public Summary(IEnumerable<Order> orders)
            {
                Filled = orders.Where(o => o.Status == OrderStatus.Filled);
                Bought = Filled.Where(o => o.Action == OrderAction.BUY);
                Sold = Filled.Where(o => o.Action == OrderAction.SELL);
                Func<Order, double> fsumm = o => o.Filled * o.FillPrice;
                Summ = Sold.Select(fsumm).Sum() - Bought.Select(fsumm).Sum();
            }
            public override string ToString()
            {
                return string.Format("Filled {1,4}, Bought {2:0.000}, Sold {3:0.000}, Summ {4:0.000}", 0, Filled.Count(), Bought.Count(), Sold.Count(), Summ);
            }
        }
    }
    public class Order : NotifyPropertyChanged, IStoreMember
    {
        public Order() { }
        public Order(Store store) : this() { this.Store = store; }
        public Order(Store store, OrderStatus orderStatus) : this(store)
        {
            this.status = orderStatus;
        }
        private OrderStatus status;
        private double fillPrice;
        private int filled;

        public int Id { get; set; }
        public string OrderRef { get; set; }
        public DateTime Created { get; set; }

        public int AlgoId { get; set; }
        [XmlIgnore]
        public Store Store { get; set; }
        [XmlIgnore]
        public Algo Algo { get { return Store.Algos.SingleOrDefault(a => a.Id == AlgoId); } }

        public OrderAction Action { get; set; }
        public OrderType OrderType { get; set; }
        public OrderingType Type { get; set; }
        public OrderStatus Status { get { return status; } set {
            if (status == value) return;
            status = value; 
            Changed(() => Status); 
            if (Store != null) Algo.Orders.StatusChanged(this); 
        } }

        public double Price { get; set; }
        public int Quantity { get; set; }
        public double FillPrice { get { return fillPrice; } set { fillPrice = value; Changed(() => FillPrice); } }
        public int Filled { get { return filled; } set {
            if (filled == value) return;
            if (Store != null) Algo.Orders.FilledChanged(this, value);
            filled = value; 
            Changed(() => Filled); 
        } }
        public override string ToString()
        {
            return string.Format("{0} {1} {2} {3}", Id, Created, Action, Price);
        }
    }
}